<html>
<head>
  <script src="../OLLoader.js"></script>
  <script type="text/javascript">
    function test_constructor(t) {
        t.plan(3);
        var control = new OpenLayers.Control();
        control.id = Math.random();
        var callbacks = {foo: "bar"};
        var options = {bar: "foo"};

        var oldInit = OpenLayers.Handler.prototype.initialize;

        OpenLayers.Handler.prototype.initialize = function(con, call, opt) {
            t.eq(con.id, control.id,
                 "constructor calls parent with the correct control");
            t.eq(call, callbacks,
                 "constructor calls parent with the correct callbacks");
            t.eq(opt, options,
                 "constructor calls parent with the correct options");
        };
        var handler = new OpenLayers.Handler.Pinch(control, callbacks, options);

        OpenLayers.Handler.prototype.initialize = oldInit;
    }

    function test_activate(t) {
        t.plan(3);
        var map = new OpenLayers.Map('map');
        var control = new OpenLayers.Control();
        map.addControl(control);
        var handler = new OpenLayers.Handler.Pinch(control);
        handler.active = true;
        var activated = handler.activate();
        t.ok(!activated,
             "activate returns false if the handler was already active");
        handler.active = false;
        handler.pinching = true;
        activated = handler.activate();
        t.ok(activated,
             "activate returns true if the handler was not already active");
        t.ok(!handler.pinching,
             "activate sets pinching to false");

    }

    function test_events(t) {
        // each handled event should be activated twice when handler is
        // activated, so:
        // 27 = 4tests * 2*3events + 1tests * 3events
        t.plan(27);

        var map = new OpenLayers.Map('map');
        var control = new OpenLayers.Control();
        map.addControl(control);
        var handler = new OpenLayers.Handler.Pinch(control);

        // list below events that should be handled (events) and those
        // that should not be handled (nonevents) by the handler
        var events = ["touchend", "touchmove", "touchstart"];
        var nonevents = ["mousedown", "mouseup", "mousemove", "mouseout",
        "click", "dblclick", "resize", "focus", "blur"];
        map.events.registerPriority = function(type, obj, func) {
                // this is one of the mock handler methods
                t.eq(OpenLayers.Util.indexOf(nonevents, type), -1,
                     "registered method is not one of the events " +
                     "that should not be handled: " + type);
                t.ok(OpenLayers.Util.indexOf(events, type) > -1,
                     "activate calls registerPriority with browser event: " + type);
                t.eq(typeof func, "function",
                     "activate calls registerPriority with a function");
                t.eq(obj["CLASS_NAME"], "OpenLayers.Handler.Pinch",
                     "activate calls registerPriority with the handler");
        };
        handler.activate();
        handler.deactivate();

        // set browser event like properties on the handler
        for(var i=0; i<events.length; ++i) {
            setMethod(events[i]);
        }
        function setMethod(key) {
            handler[key] = function() {return key;};
        }

        map.events.registerPriority = function(type, obj, func) {
            var r = func();
            if(typeof r == "string") {
                t.eq(r, type,
                     "activate calls registerPriority with the correct method");
            }
        }
        handler.activate();

    }

    function test_callbacks(t) {
        t.plan(23);

        var map = new OpenLayers.Map('map', {controls: []});

        var control = new OpenLayers.Control();
        map.addControl(control);

        // set fake values for touches
        var testEvents = {
            start: {
                type: 'start',
                touches: [{
                    clientX: 100,
                    clientY: 0
                }, {
                    clientX: 0,
                    clientY: 0
                }]
            },
            move: {
                type: 'move',
                touches: [{
                    clientX: 100,
                    clientY: 0
                }, {
                    clientX: 20,
                    clientY: 0
                }]
            },
            done: {
                type: 'done',
                touches: []
            }
        };
        
        // set callback methods
        var customCb = OpenLayers.Function.False;
        var cb = function(evt) {
            var tch = testEvents[evt.type].touches;
            t.ok(evt.touches[0].clientX == tch[0].clientX &&
                evt.touches[0].clientY == tch[0].clientY,
                "touchstart sets first touch position correctly in evt");
            t.ok(evt.touches[1].clientX == tch[1].clientX &&
                evt.touches[1].clientY == tch[1].clientY,
                "touchstart sets second touch position correctly in evt");
            t.eq(handler.start.distance, 100, "start distance is " +
                "always the same");
            customCb.apply(this, arguments);
        }
        var callbacks = {
            start: cb,
            move: cb,
            done: customCb
        };

        var handler = new OpenLayers.Handler.Pinch(control, callbacks);
        handler.activate();

        var old_isMultiTouch = OpenLayers.Event.isMultiTouch;
        var old_stop = OpenLayers.Event.stop;
        
        // test single touch
        OpenLayers.Event.isMultiTouch = function() {
            return false;
        }
        handler.started = true;
        handler.start = {
            distance: 100,
            delta: 0,
            scale: 1
        };
        handler.last = {
            distance: 150,
            delta: 10,
            scale: 1.5
        };
        map.events.triggerEvent("touchstart", testEvents.start);
        t.ok(!handler.started, "1) touchstart (singletouch) sets started to false");
        t.eq(handler.start, null, "1) touchstart (singletouch) sets start to null");
        t.eq(handler.last, null, "1) touchstart (singletouch) sets last to null");

        OpenLayers.Event.stop = function(evt, allowDefault) {
            if(allowDefault) {
                t.fail(
                    "touchstart is prevented from falling to other elements");
            }
        }
        OpenLayers.Event.isMultiTouch = function(evt) {
            var res = old_isMultiTouch(evt);
            t.ok(res, "fake event is a mutitouch touch event");
            return res;
        }
        customCb = function(evt, pinchdata) {
            t.eq(pinchdata.distance, 100, "2) calculated distance is correct");
            t.eq(pinchdata.delta, 0, "2) calculated delta is correct");
            t.eq(pinchdata.scale, 1, "2) calculated scale is correct");
        }
        map.events.triggerEvent("touchstart", testEvents.start);
        t.ok(handler.started, "2) touchstart sets the started flag to true");
        t.ok(!handler.pinching, "2) touchstart sets the pinching flag to false");

        customCb = function(evt, pinchdata) {
            t.eq(pinchdata.distance, 80, "3) calculated distance is correct");
            t.eq(pinchdata.delta, 20, "3) calculated delta is correct");
            t.eq(pinchdata.scale, 0.8, "3) calculated scale is correct");
        }
        map.events.triggerEvent("touchmove", testEvents.move);
        t.ok(handler.started, "3) started flag still set to true");
        t.ok(handler.pinching, "3) touchmove sets the pinching flag to true");


        customCb = function(evt, first, last) {
            t.eq(first.distance, 100, "4) calculated distance is correct");
            t.eq(first.delta, 0, "4) calculated delta is correct");
            t.eq(first.scale, 1, "4) calculated scale is correct");
            t.eq(last.distance, 80, "4) calculated distance is correct");
            t.eq(last.delta, 20, "4) calculated delta is correct");
            t.eq(last.scale, 0.8, "4) calculated scale is correct");
        }
        map.events.triggerEvent("touchend", testEvents.done);
        t.ok(!handler.started, "4) started flag is set to false");
        t.ok(!handler.pinching, "4) touchdone sets the pinching flag to false");

        OpenLayers.Event.stop = old_stop;
        OpenLayers.Event.isMultiTouch = old_isMultiTouch;

        // test move or done before start
        customCb = function(evt) {
            t.fail("should not pass here")
        }
        map.events.triggerEvent("touchmove", testEvents.move);
        map.events.triggerEvent("touchend", testEvents.end);

    }

    function test_deactivate(t) {
        t.plan(6);
        var map = new OpenLayers.Map('map');
        var control = new OpenLayers.Control();
        map.addControl(control);
        var handler = new OpenLayers.Handler.Pinch(control);
        handler.active = false;
        var deactivated = handler.deactivate();
        t.ok(!deactivated,
             "deactivate returns false if the handler was not already active");
        handler.active = true;
        handler.pinching = true;
        deactivated = handler.deactivate();
        t.ok(deactivated,
             "deactivate returns true if the handler was active already");
        t.ok(!handler.started,
             "deactivate sets started to false");
        t.ok(!handler.pinching,
             "deactivate sets pinching to false");
        t.ok(handler.start == null,
             "deactivate sets start to null");
        t.ok(handler.last == null,
             "deactivate sets start to null");
    }


  </script>
</head>
<body>
    <div id="map" style="width: 300px; height: 150px;"/>
</body>
</html>
